namespace EyeOpen.Log4NetExtensions.Appenders
{
    using System.Data;
    using log4net.Appender;
    using log4net.Layout;

    public class SqlAdoNetAppender : DbAdoNetAppender
    {
        public SqlAdoNetAppender()
        {
            BufferSize = 1;
            ConnectionType = "System.Data.SqlClient.SqlConnection";
            CommandText = "INSERT INTO Log ([User],[Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@user, @log_date, @thread, @level, @logger, @message, @exception)";
        }

        protected override void AddParametersList()
        {
            AddParameter(CreateStringCustomAdoNetParameter("user", 50));
            AddParameter(CreateDateAdoNetParameter("log_date"));
            AddParameter(CreateStringAdoNetParameter("thread", 255));
            AddParameter(CreateStringAdoNetParameter("level", 50));
            AddParameter(CreateStringAdoNetParameter("logger", 255));
            AddParameter(CreateStringAdoNetParameter("message", 4000));
            AddParameter(CreateExceptionAdoNetParameter("exception"));
        }

        private AdoNetAppenderParameter CreateStringCustomAdoNetParameter(string parameterName, int size)
        {
            var conversionPattern = string.Format("%property{{{0}}}", parameterName);
            
            return
                new AdoNetAppenderParameter
                {
                    ParameterName = GetParameterName(parameterName),
                    Layout = new Layout2RawLayoutAdapter(new PatternLayout(conversionPattern)),
                    DbType = DbType.String,
                    Size = size
                };
        }

        private AdoNetAppenderParameter CreateDateAdoNetParameter(string parameterName)
        {
            return 
                new AdoNetAppenderParameter
                    {
                        ParameterName = GetParameterName(parameterName),
                        Layout = RawTimeStampLayout,
                        DbType = DbType.DateTime
                    };
        }

        private AdoNetAppenderParameter CreateStringAdoNetParameter(string parameterName, int size)
        {
            return
                new AdoNetAppenderParameter
                    {
                        ParameterName = GetParameterName(parameterName),
                        Layout = new Layout2RawLayoutAdapter(new PatternLayout(GetPatternName(parameterName))),
                        DbType = DbType.String,
                        Size = size
                    };
        }

        private AdoNetAppenderParameter CreateExceptionAdoNetParameter(string parameterName)
        {
            return
                new AdoNetAppenderParameter
                    {
                        ParameterName = GetParameterName(parameterName),
                        Layout = new Layout2RawLayoutAdapter(ExceptionLayout),
                        DbType = DbType.String,
                        Size = 2000
                    };
        }

        private string GetPatternName(string parameterName)
        {
            return string.Format("%{0}", parameterName);
        }

        private string GetParameterName(string parameterName)
        {
            return string.Format("@{0}", parameterName);
        }
    }
}